package com.hongawen.testsharding.sharding;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.google.common.collect.Range;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

/**
 * Description:
 *
 * @author Jam
 */
public class LocalDateShardingAlgorithm implements StandardShardingAlgorithm<Comparable<?>> {



    /**
     * 插入分片算法
     *
     * @param availableTargetNames 可用的数据表
     * @param preciseShardingValue 分片值
     * @return 返回选中的数据表
     */
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<Comparable<?>> preciseShardingValue) {
        LocalDate localDateTime = (LocalDate) preciseShardingValue.getValue();
        DateTime dateTime = DateUtil.beginOfQuarter(Date.from(localDateTime.atStartOfDay(ZoneId.systemDefault()).toInstant()));
        String dayFormatStr = dateTime.toString(DatePattern.SIMPLE_MONTH_PATTERN);
        for (String availableTargetName : availableTargetNames) {
            if (availableTargetName.endsWith(dayFormatStr)) {
                return availableTargetName;
            }
        }
        return null;
    }


    /***
     * 日期作为时间条件范围处理
     * @author hongawen
     * @date 2023/6/30 15:15
     * @return Collection<String>
     */
    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames, RangeShardingValue<Comparable<?>> shardingValue) {
        //用来装表名
        Set<String> tableNames = new HashSet<>();
        Iterator<String> iterator = availableTargetNames.iterator();
        String tableName = iterator.next();
        //表名前缀
        String name = tableName.substring(0, tableName.lastIndexOf("_"));

        //取出时间范围，判断该时间范围对应的哪些表后缀
        Range<Comparable<?>> valueRange = shardingValue.getValueRange();
        LocalDate lowerDate = (LocalDate) valueRange.lowerEndpoint();
        LocalDate upperDate = (LocalDate) valueRange.lowerEndpoint();
        //起始季度
        DateTime lowerDateTime = DateUtil.beginOfQuarter(Date.from(lowerDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
        String lowerFormatStr = lowerDateTime.toString(DatePattern.SIMPLE_MONTH_PATTERN);
        //结束季度
        DateTime upperDateTime = DateUtil.beginOfQuarter(Date.from(upperDate.atStartOfDay(ZoneId.systemDefault()).toInstant()));
        String upperDayFormatStr = upperDateTime.toString(DatePattern.SIMPLE_MONTH_PATTERN);
        while (!lowerFormatStr.equals(upperDayFormatStr)) {
            if (availableTargetNames.contains(name + "_" + lowerFormatStr)) {
                tableNames.add(name + "_" + lowerFormatStr);
            }
            //升级下一季度
            lowerDateTime = DateUtil.endOfQuarter(lowerDateTime);
            LocalDateTime tempLocalDateTime = LocalDateTimeUtil.of(lowerDateTime);
            tempLocalDateTime.plusDays(1L);
            lowerDateTime = DateUtil.beginOfQuarter(Date.from(tempLocalDateTime.atZone(ZoneId.systemDefault()).toInstant()));
            lowerFormatStr = lowerDateTime.toString(DatePattern.SIMPLE_MONTH_PATTERN);
        }
        if (availableTargetNames.contains(name + "_" + upperDayFormatStr)) {
            tableNames.add(name + "_" + upperDayFormatStr);
        }
        if (CollectionUtils.isNotEmpty(tableNames)) {
            return tableNames;
        }

        return availableTargetNames;
    }


    @Override
    public Properties getProps() {
        return null;
    }

    @Override
    public void init(Properties properties) {

    }

    public static void main(String[] args) {
        DateTime dateTime = new DateTime("2017-01-05 12:34:23", DatePattern.NORM_DATETIME_FORMAT);
        System.out.println(DateUtil.beginOfQuarter(dateTime));
        System.out.println(DateUtil.endOfQuarter(dateTime));
    }
}
